#include "bs_ws.h"

using namespace std;

void BsWebSocket::handleNewMessage(const WebSocketConnectionPtr &wsConnPtr, std::string &&message,
                                   const WebSocketMessageType &type) {
    if (type == WebSocketMessageType::Ping ||
        type == WebSocketMessageType::Pong ||
        type == WebSocketMessageType::Close) {
        LOG_DEBUG << "[WS] message ping pong: " << message;
        return;
    }

    if (type != WebSocketMessageType::Text) {
        LOG_ERROR << "[WS] unsupported message type " << (int) type;
        return;
    }

    LOG_DEBUG << "[WS] message from: " << wsConnPtr->peerAddr().toIpPort()
              << ", text: " << message;

    BsClient &c = wsConnPtr->getContextRef<BsClient>();
    wsRooms.publish(c.roomId, message);
    // wsConnPtr->send(message);
}

void BsWebSocket::handleNewConnection(const HttpRequestPtr &req, const WebSocketConnectionPtr &wsConnPtr) {
    LOG_DEBUG << "[WS] new connection!";
    wsConnPtr->send("conn success.");
    BsClient bsc;
    bsc.userId = req->getParameter("user_id");
    bsc.roomId = req->getParameter("room_id");
    bsc.bsId = wsRooms.subscribe(bsc.roomId,
                                 [wsConnPtr](const std::string &topic,
                                             const std::string &message) {
                                     (void) topic;
                                     wsConnPtr->send(message);
                                 });
    wsConnPtr->setContext(std::make_shared<BsClient>(std::move(bsc)));
}

void BsWebSocket::handleConnectionClosed(const WebSocketConnectionPtr &wsConnPtr) {
    LOG_DEBUG << "[WS] connection closed!";
    BsClient &c = wsConnPtr->getContextRef<BsClient>();
    wsRooms.unsubscribe(c.roomId, c.bsId);
}

void BsWebSocket::sendHeartbeatToAll(const std::string &room) const {
    wsRooms.publish(room, std::format("ping"));
}

void BsWebSocket::sendMessageToAll(const std::string &room, const std::string& message) const {
    wsRooms.publish(room, message);
}